package com.dasel.math

import java.util.concurrent.*;
import groovy.util.concurrent.*;
import groovy.util.*;

import groovy.lang.Function1
import groovyx.gpars.*

/**
 * Created by IntelliJ IDEA.
 * User: benoit
 * Date: 28-Feb-2010
 * Time: 18:12:22
 * To change this template use File | Settings | File Templates.
 */
@Typed
class Asrid {

    private static CallLaterPool poool = CallLaterExecutors.newFixedThreadPool(10);

    Integer rows
    Integer cols
    double[][] matrix

    public Asrid plus(Asrid right) {
        double[][] results = new double[rows][cols]
        def vects = new ArrayList<Future<double[]>>()

        for (int i = 0; i < rows; i++) {
            Future<double[]> fut = pluss(this.matrix[i], right.matrix[i], poool)
            vects << fut
        }
        int count = rows
        while (count > 0) {
            for (int i = 0; i < rows; i++) {
                if (vects[i].isDone()) {
                    count--
                    results[i] = vects[i].get()
                }
            }
        }
        return new Asrid(matrix: results, rows: rows, cols: cols)
    }

    public Asrid plus(Number right) {
        double[][] results = new double[rows][cols];
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                results[i][j] = this.matrix[i][j] + right
            }
        }
        return new Asrid(matrix: results, rows: rows, cols: cols)
    }


    public Asrid multiply(Asrid right) {
        double[][] results = new double[rows][cols]
        def vects = new ArrayList<Future<double[]>>()

        for (int i = 0; i < rows; i++) {
            Future<double[]> fut = mult(this.matrix[i], right.matrix[i], poool)
            vects << fut
        }
        int count = rows
        while (count > 0) {
            for (int i = 0; i < rows; i++) {
                if (vects[i].isDone()) {
                    count--
                    results[i] = vects[i].get()
                }
            }
        }
        return new Asrid(matrix: results, rows: rows, cols: cols)
    }

    public Asrid multiply(Number right) {
        double[][] results = new double[rows][cols];
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                results[i][j] = this.matrix[i][j] * right
            }
        }
        return new Asrid(matrix: results, rows: rows, cols: cols)
    }

    @Async
    double[] pluss(double[] a, double[] b) {
        double[] r = new double[a.length];
        for (int j = 0; j < r.length; j++) {
            r[j] = a[j] + b[j];
        }
        return r;
    }

    @Async
    double[] mult(double[] a, double[] b) {
        double[] r = new double[a.length];
        for (int j = 0; j < r.length; j++) {
            r[j] = a[j] * b[j];
        }
        return r;
    }

}